home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Extensions / img / Lib / imgjpeg.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  4.4 KB  |  138 lines

  1. """A module that reads JPEG files using the SGI Compression Library.
  2.  
  3. This module should only be used in a python-interpreter with the cl
  4. module configured, otherwise the builtin imgjpeg module is better."""
  5.  
  6. import cl
  7. from imgformat import rgb, rgb_b2t, xrgb8, xrgb8_b2t, xgrey, xgrey_b2t, \
  8.               rgb8, rgb8_b2t, grey, grey_b2t, error
  9. import sys
  10.  
  11. class reader:
  12.     def __init__(self, file):
  13.         if type(file) == type(''):
  14.             self._filename = file
  15.             self._file = f = open(file, 'rb')
  16.     else:
  17.             self._filename = '<open file>'
  18.             self._file = f = file
  19.     header = f.read(16)
  20.     scheme = cl.QueryScheme(header)
  21.     self._decompressor = decomp = cl.OpenDecompressor(scheme)
  22.     size = cl.QueryMaxHeaderSize(scheme)
  23.     if size > len(header):
  24.             header = header + f.read(size - len(header))
  25.     headersize = decomp.ReadHeader(header)
  26.     self.width = decomp.GetParam(cl.IMAGE_WIDTH)
  27.     self.height = decomp.GetParam(cl.IMAGE_HEIGHT)
  28.     self.format_choices = rgb, rgb_b2t, xrgb8, xrgb8_b2t, xgrey, xgrey_b2t
  29.     self.format = rgb        # default format
  30.  
  31.     def args(self):
  32.     return self.__dict__
  33.     
  34.     def read(self):
  35.     if self.format in (rgb, rgb_b2t):
  36.             original_format = cl.RGBX
  37.     elif self.format in (xrgb8, xrgb8_b2t, rgb8, rgb8_b2t):
  38.             original_format = cl.RGB332
  39.     elif self.format in (xgrey, xgrey_b2t, grey, grey_b2t):
  40.             original_format = cl.GRAYSCALE
  41.     else:
  42.             raise error, 'Unknown format'
  43.     if self.format in (rgb_b2t, xrgb8_b2t, xgrey_b2t, rgb8_b2t, grey_b2t):
  44.             orientation = cl.BOTTOM_UP
  45.     else:
  46.             orientation = cl.TOP_DOWN
  47.     width = self.width
  48.     if original_format == cl.RGB332 and sys.platform == 'irix5':
  49.             # Irix 5.3 uses more buffer than it should, so allocate some extra
  50.             width = (width + 3) & ~3
  51.     bbp = cl.BytesPerPixel(original_format)
  52.     params = [cl.ORIGINAL_FORMAT, original_format,
  53.           cl.ORIENTATION, orientation,
  54.           cl.FRAME_BUFFER_SIZE, width * self.height * bbp]
  55.         decomp = self._decompressor
  56.     decomp.SetParams(params)
  57.     self._file.seek(0)
  58.     data = decomp.Decompress(1, self._file.read())
  59.         if self.width & 1 and \
  60.            decomp.GetParam(cl.INTERNAL_FORMAT) == cl.FORMAT_YCbCr422DC:
  61.             # IRIX has difficulty with odd-width images.  It rounds
  62.             # the width down to an even number, so we double the
  63.             # right-most pixel so that the image gets the original
  64.             # width again.
  65.             import string
  66.             rv = []
  67.             w = (self.width - 1) * bbp
  68.             for i in range(0, self.height * w, w):
  69.                 rv.append(data[i:i+w] + data[i+w-bbp:i+w])
  70.             return string.join(rv, '')
  71.         # only return the image, not the extra space
  72.         return data[:self.width*self.height*bbp]
  73.  
  74.     def write(self, data):
  75.     raise error, 'Cannot write() to reader'
  76.  
  77. class writer:
  78.     def __init__(self, file):
  79.         if type(file) == type(''):
  80.         self._filename = file
  81.         self._fp = None
  82.     else:
  83.         self._filename = "<open file>"
  84.         self._fp = file
  85.     self.format_choices = rgb, rgb_b2t, xrgb8, xrgb8_b2t, xgrey, xgrey_b2t
  86.     self.format = rgb
  87.  
  88.     def args(self):
  89.     return self.__dict__
  90.     
  91.     def _get(self, attr):
  92.     try:
  93.             return getattr(self, attr)
  94.     except AttributeError:
  95.             raise error, "Required attribute '%s' missing"%attr
  96.  
  97.     def read(self):
  98.     raise error, 'Cannot read() from writer'
  99.  
  100.  
  101.     def write(self, data):
  102.     width = self._get('width')
  103.     height = self._get('height')
  104.     format = self._get('format')
  105.     if format in (rgb, rgb_b2t):
  106.             original_format = cl.RGBX
  107.     elif format in (xrgb8, xrgb8_b2t):
  108.             original_format = cl.RGB332
  109.     elif format in (xgrey, xgrey_b2t):
  110.             original_format = cl.GRAYSCALE
  111.     else:
  112.             raise error, 'Unknown format'
  113.     if format in (rgb_b2t, xrgb8_b2t, xgrey_b2t):
  114.             orientation = cl.BOTTOM_UP
  115.     else:
  116.             orientation = cl.TOP_DOWN
  117.     if width * height * cl.BytesPerPixel(original_format) != len(data):
  118.             raise error, 'Incorrect datasize'
  119.     params = [cl.ORIGINAL_FORMAT, original_format,
  120.           cl.ORIENTATION, orientation,
  121.           cl.IMAGE_WIDTH, width,
  122.           cl.IMAGE_HEIGHT, height]
  123.     try:
  124.             quality = self.quality
  125.     except AttributeError:
  126.             pass
  127.     else:
  128.             params.append(cl.QUALITY_FACTOR)
  129.             params.append(quality)
  130.     compressor = cl.OpenCompressor(cl.JPEG)
  131.     compressor.SetParams(params)
  132.     data = compressor.Compress(1, data)
  133.     if self._fp:
  134.             file = self._fp
  135.     else:
  136.             file = open(self._filename, 'wb')
  137.     file.write(data)
  138.